package com.example.quartzdemo.quartz;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.quartzdemo.entity.QuartzTask;
import com.example.quartzdemo.entity.dto.QuartzTaskDto;
import com.example.quartzdemo.service.QuartzTaskRepository;
import com.example.quartzdemo.util.job.ConcurrentQuartzJob;
import com.example.quartzdemo.util.job.NonConcurrentQuartzJob;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import java.util.List;
import java.util.Optional;

@Service
public class QuartzTaskService  {
    @Autowired
    Scheduler scheduler;
    @Autowired
    QuartzTaskRepository taskRepo;

    @PostConstruct
    public void init() throws Exception {
        taskRepo.findAll().forEach(t -> {
            try {
                if ("ENABLED".equals(t.getStatus())) schedule(t);
            } catch (Exception e) {e.printStackTrace();}
        });
    }
    public void schedule(QuartzTask t) throws Exception {
        Class<? extends Job> jobCls = t.getConcurrent()
                ? ConcurrentQuartzJob.class
                : NonConcurrentQuartzJob.class;
        JobDetail job = JobBuilder.newJob(jobCls)
                .withIdentity(t.getTaskId(),"DEFAULT")
                .usingJobData("taskId", t.getTaskId())
                .usingJobData("className", t.getClassName())
                .usingJobData("methodName", t.getMethodName())
                .storeDurably().build();
        Trigger trigger = TriggerBuilder.newTrigger()
                .withIdentity(t.getTaskId() +"_trigger","DEFAULT")
                .withSchedule(CronScheduleBuilder.cronSchedule(t.getCron()))
                .build();
        scheduler.scheduleJob(job, trigger);
    }
    @Transactional(rollbackFor = Exception.class)
    public String add(QuartzTaskDto dto) throws Exception {
        QuartzTask t = taskRepo.findByTaskId(dto.getTaskId()).orElse(new QuartzTask());
        if(t.getId()!=null){
            return "该"+t.getTaskId()+"任务已存在";
        }
        t.setTaskId(dto.getTaskId()); t.setCron(dto.getCron());
        t.setClassName(dto.getClassName()); t.setMethodName(dto.getMethodName());
        t.setStatus("ENABLED"); t.setConcurrent(dto.getConcurrent());
        taskRepo.save(t);
        JobKey jk = new JobKey(dto.getTaskId(),"DEFAULT");
        if (scheduler.checkExists(jk)) scheduler.deleteJob(jk);
        schedule(t);
        return null;
    }
    @Transactional(rollbackFor = Exception.class)
    public String update(QuartzTask dto) throws Exception {
        QuartzTask t = taskRepo.findByTaskId(dto.getTaskId()).orElse(new QuartzTask());
        if(t==null){
            return "该"+t.getTaskId()+"任务不存在";
        }
        dto.setStatus("ENABLED");
        taskRepo.updateById(dto);
        JobKey jk = new JobKey(dto.getTaskId(),"DEFAULT");
        if (scheduler.checkExists(jk)) scheduler.deleteJob(jk);
        schedule(t);
        return null;
    }
    @Transactional(rollbackFor = Exception.class)
    public void remove(String taskId) throws Exception {
        taskRepo.findByTaskId(taskId).ifPresent(t -> taskRepo.delete(t));
        scheduler.deleteJob(new JobKey(taskId,"DEFAULT"));
    }
    @Transactional(rollbackFor = Exception.class)
    public void pause(String taskId) throws Exception {
        scheduler.pauseJob(new JobKey(taskId,"DEFAULT"));
        taskRepo.findByTaskId(taskId).ifPresent(t -> {
            t.setStatus("DISABLED"); taskRepo.updateById(t);});
    }
    @Transactional(rollbackFor = Exception.class)
    public void resume(String taskId) throws Exception {
        JobKey jk = new JobKey(taskId,"DEFAULT");
        taskRepo.findByTaskId(taskId).ifPresent(t -> {
            try {
                if (scheduler.checkExists(jk)) {
                    scheduler.resumeJob(jk);
                }else{
                    schedule(t);
                }
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            t.setStatus("ENABLED"); taskRepo.updateById(t);});
    }
}

